#ifndef _CU_UINT1_H_
#define _CU_UINT1_H_

//**********************************************************************************
// uint1 operators and functions
//**********************************************************************************

SDH_CALL uint1 operator + (const uint1 & u, uint v) { uint1 r = { u.x + v }; return r; }
SDH_CALL uint1 operator - (const uint1 & u, uint v) { uint1 r = { u.x - v }; return r; }
SDH_CALL uint1 operator * (const uint1 & u, uint v) { uint1 r = { u.x * v }; return r; }
SDH_CALL uint1 operator / (const uint1 & u, uint v) { uint1 r = { u.x / v }; return r; }

SDH_CALL uint1 operator + (uint v, const uint1 & u) { uint1 r = { v + u.x }; return r; }
SDH_CALL uint1 operator - (uint v, const uint1 & u) { uint1 r = { v - u.x }; return r; }
SDH_CALL uint1 operator * (uint v, const uint1 & u) { uint1 r = { v * u.x }; return r; }
SDH_CALL uint1 operator / (uint v, const uint1 & u) { uint1 r = { v / u.x }; return r; }

SDH_CALL uint1 operator + (const uint1 & u, const uint1 & v) { uint1 r = { u.x + v.x }; return r; }
SDH_CALL uint1 operator - (const uint1 & u, const uint1 & v) { uint1 r = { u.x - v.x }; return r; }
SDH_CALL uint1 operator * (const uint1 & u, const uint1 & v) { uint1 r = { u.x * v.x }; return r; }
SDH_CALL uint1 operator / (const uint1 & u, const uint1 & v) { uint1 r = { u.x / v.x }; return r; }

SDH_CALL uint1   operator - (const uint1 & v) { uint1 r = { -v.x }; return r; }

SDH_CALL uint1 & operator += (uint1 & u, const uint1 & v) { u.x += v.x; return u; }
SDH_CALL uint1 & operator -= (uint1 & u, const uint1 & v) { u.x -= v.x; return u; }
SDH_CALL uint1 & operator *= (uint1 & u, const uint1 & v) { u.x *= v.x; return u; }
SDH_CALL uint1 & operator /= (uint1 & u, const uint1 & v) { u.x /= v.x; return u; }

SDH_CALL uint1 & operator += (uint1 & u, uint v) { u.x += v; return u; }
SDH_CALL uint1 & operator -= (uint1 & u, uint v) { u.x -= v; return u; }
SDH_CALL uint1 & operator *= (uint1 & u, uint v) { u.x *= v; return u; }
SDH_CALL uint1 & operator /= (uint1 & u, uint v) { u.x /= v; return u; }

SDH_CALL uint1 catmullrom (const uint1 & P0, const uint1 & P1, const uint1 & P2, const uint1 & P3, float t)
{
  const float ts = t * t;
  const float tc = t * ts;

  return (P0 * (-tc + 2.0f * ts - t) + P1 * (3.0f * tc - 5.0f * ts + 2.0f) + P2 * (-3.0f * tc + 4.0f * ts + t) + P3 * ( tc - ts)) * 0.5f;
}
SDH_CALL uint1 lerp      (const uint1 & u, const uint1 & v, float t ) { return u + t * (v - u); }
SDH_CALL uint  dot       (const uint1 & u, const uint1 & v) { return (u.x*v.x); }
SDH_CALL uint1 clamp     (const uint1 & u, uint a, uint b) { uint1 r = { clamp(u.x, a, b) }; return r; }

SDH_CALL uint1 saturate  (const uint1 & u) { return clamp(u, 0.0f, 1.0f); }

SDH_CALL uint1 min(const uint1 & u, const uint1 & v){ uint1 r = {min(u.x, v.x)}; return r; }
SDH_CALL uint1 max(const uint1 & u, const uint1 & v){ uint1 r = {max(u.x, v.x)}; return r; }

SDH_CALL uint    sad (const uint1 & u, const uint1 & v) { return (abs(u.x - v.x)); } // Sum of Absolute Differences for x components
SDH_CALL uint    ssd (const uint1 & u, const uint1 & v) { return (sqr(u.x - v.x)); } // Sum of Squared Differences for x components

SDH_CALL float  length (const uint1 & u) { return abs(u.x); }

#endif